from database.park_location_record_table import ParkLocationRecordTable
from manager.lock_manager import LockManager
from model.park_spider import ParkSpider
from model.park_platform import ParkPlatform
from model.car_number import CarNumber
from model.result import Result
from model.error import BannedAccountError, ParkSpiderError, ParkSpiderErrorCode

import dateutil.parser as dateutil

import re
import time
import json
import common.verify as verify

import common.http as http
import threading
from common.logger import logger
import spider_config
import random


class SuParkSpider(ParkSpider):
    def platform(self) -> ParkPlatform:
        return ParkPlatform(spider_config.su_park_id)

    def blockPuzzle(self, account):
        headers = {
            "Content-Type": "application/json",
            "User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/",
            # "accessToken": account,
            "Cookie": f"pp_user_hash={account['userhash']};  pp_user_id={account['userid']}",
        }

        url = "https://cloud.keytop.cn/captcha-middle-api/blockPuzzle/front/getToken"

        data = {"captchaType": "blockPuzzle"}

        rsp = http.post(
            url,
            headers=headers,
            data=json.dumps(data),
            proxies=self.getProxy(),
            timeout=self.getTimeout(),
        )

        if rsp.status_code != 200:
            return False, f"status_code:{rsp.status_code}, url:{url}"

        j = rsp.json()

        if j["repCode"] != "0000":
            return False, j.dumps()

        # 随机0-1秒
        time.sleep(random.random() + 1)

        token = j["repData"]["token"]

        bg = j["repData"]["originalImageBase64"]
        jg = j["repData"]["jigsawImageBase64"]

        px = verify.blockPuzzle(bg, jg)
        py = 5

        headers["token"] = token
        headers["px"] = str(px)
        headers["py"] = str(py)

        url = "https://cloud.keytop.cn/service/front/userCenter/unsealed"

        rsp = http.post(
            url, headers=headers, proxies=self.getProxy(), timeout=self.getTimeout()
        )

        if rsp.status_code != 200:
            return False, f"status_code:{rsp.status_code}, url:{url}"

        rspJson = rsp.json()

        info = f"message:{rspJson['message']}, bk:{bg}, jg:{jg}, px:{px}, py:{py}"

        return rspJson["code"] == 2000, info

    def query(self, carNumber: CarNumber) -> Result:
        account = self.getAccount()

        if not account:
            raise ParkSpiderError(ParkSpiderErrorCode.SuAccountEmpty)

        result = Result()
        result.platform = self.platform()
        result.car_number = carNumber

        url = "https://cloud.keytop.cn/service/front/parking/wxa/city"

        headers = {
            "Content-Type": "application/json",
            "User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/",
            # "accessToken": account,
            "Cookie": f"pp_user_hash={account['userhash']};  pp_user_id={account['userid']}",
        }

        data = {
            "lpn": f"{carNumber.province}{carNumber.city}{carNumber.number}",
        }

        with LockManager.instance().get(self.platform().id, account["userid"]):
            rsp = http.post(
                url,
                headers=headers,
                data=json.dumps(data),
                proxies=self.getProxy(),
                timeout=self.getTimeout(),
            )

            rspJson = rsp.json()

            if rspJson["code"] == 3004:
                raise BannedAccountError(account['userid'])

            sub_code = rspJson["subCode"]

            if sub_code == 998:
                logger.warning(f"{account['userid']} 违规账号")
                raise BannedAccountError(account['userid'])
            elif sub_code == 999:
                logger.debug(f"{account['userid']} 人机验证中")
                
                repeat = 0

                while True:
                    success, info = self.blockPuzzle(account)
                    if success:
                        logger.success(f"{account['userid']} 滑块验证成功,继续查询")
                        break
                    else:
                        if repeat > 10:
                            result.message = f"{account['userid']} 滑块验证失败"
                            logger.error(result.message)
                            return result
                        else:
                            repeat += 1
                            result.message = f"{account['userid']} 验证失败,重试{repeat}次({info})"
                            logger.debug(result.message)

                return self.query(carNumber)

            logger.debug(f"速停车测试:{str(carNumber)}: {rspJson}")

            if rsp.status_code != 200:
                result.error_code = rsp.status_code
                result.message = rsp.text
                return result

            result.error_code = rspJson["code"]
            result.success = rspJson["code"] == 2000
            result.message = rspJson["message"] if "message" in rspJson else ""

            if not result.success:
                return result

            data["encodeLotId"] = rspJson["data"]["encodeLotId"]
            data["token"] = rspJson["data"]["token"]

            url = "https://cloud.keytop.cn/service/front/paymentCard/compose"

            rsp = http.post(
                url,
                headers=headers,
                data=json.dumps(data),
                proxies=self.getProxy(),
                timeout=self.getTimeout(),
            )

            if rsp.status_code != 200:
                result.error_code = rsp.status_code
                result.message = rsp.text
                return result

            rspJson = rsp.json()

            result.error_code = rspJson["code"]
            result.success = rspJson["code"] == 2000
            result.message = rspJson["message"] if "message" in rspJson else ""

            if not result.success:
                return result

            result.enter_time = dateutil.parse(
                rspJson["data"]["orderConfirmInfo"]["comeTime"]
            )
            result.price = rspJson["data"]["orderConfirmInfo"]["cashFee"] / 100

            result.park_name = rspJson["data"]["orderConfirmInfo"]["lotName"]

            if "correction_url" in rspJson["data"]:
                correction_url = rspJson["data"]["correction_url"]
                lotid = re.search(r"lotId=(\d+)", correction_url).group(1)
            else:
                lotid = rspJson["data"]["orderConfirmInfo"]["lotId"]

            # 获取停车场名称接口有时会返回502，重试一般都能好
            for i in range(5):
                url = f"https://fms-service.keytop.cn/cn.keytop.stc.cp.privacyprotection.IsShowLpn/1.0/?plateNum=0&lotId={lotid}&source=10"
                rsp = http.get(url, proxies=self.getProxy(), timeout=self.getTimeout())
                if rsp.status_code == 200:
                    result.park_name = rsp.json()["data"]["lotName"]
                    break
                else:
                    logger.warning(f"速停车获取停车场名称{rsp.status_code},重试{i+1}次")
                    
            with ParkLocationRecordTable(spider_config.su_park_id) as db:
                record = db.query_by_name(result.park_name)
                if record:
                    result.park_name = record
            # 获取入场图片接口
            # https://ss-service.keytop.cn/cn.keytop.stc.cp.misc.front.payment.ParkingImg/1.0/?_=1670309671158&lotId=NJ6dbYa1ETT-C884oomyNQ%3D%3D&imgName=20221205002456605_192.168.171.131_011492.jpg

            return result
